<html>  
   <head>  
        <meta charset="utf-8">  
    <title>What 中文</title>  
       <script type="text/javascript" src="d3.js"></script>  
      <style type="text/css">
        .link {
          
          fill: none;
          stroke: #f00;
          stroke-width: 1.5px;
        }
        .node.inactive{
          opacity:0.4;
        }
        line{
          stroke:#f00;
        }
        line.inactive{
          opacity:0.4;
          stroke:black;
        }
        .link.inactive{
          opacity:0.4;
          stroke:black;
        }
      </style>
    </head>  
    <body>          
    </body>  
    <script type="text/javascript">  
       var nodes = [ { name: "普总"    }, 
            { name: "普通人" },
            { name: "徐老师"    },
            { name: "徐老湿"   },
            { name: "皮条张"   },
            { name: "徐嫖客"    },
            { name: "张三"    },
            { name: "李四"    },
            { name: "老普"  },
            { name: "王五"       },
            { name: "王麻子"  },
            { name: "普徐老湿"       },
            { name: "皮条客"    } ];
           
      var edges = [  { source : 0  , target: 1 } ,
             { source : 1  , target: 2 } ,
             { source : 2  , target: 3 } ,
             { source : 2  , target: 4 } ,
             { source : 3  , target: 4 } ,
             { source : 4  , target: 5 } ,
             { source : 4  , target: 0 } ,
             { source : 5  , target: 6 } ,
             { source : 6  , target: 7 } ,
             { source : 7  , target: 8 } ,
             { source : 8  , target: 9 } ,
             { source : 9  , target: 10 } ,
             { source : 10 , target: 11 } ,
             { source : 11 , target: 12 } ,
             { source : 12 , target: 0 } ];
    var width = 600;
    var height = 600;
    var img_w = 20;
    var img_h = 20;
    
    var svg = d3.select("body").append("svg")
                .attr("width",width)
                .attr("height",height);
  var defs = svg.append("defs");

  var arrowMarker = defs.append("marker")
            .attr("id","arrow")
            .attr("markerUnits","strokeWidth")
            .attr("markerWidth","12")
            .attr("markerHeight","12")
            .attr("viewBox","0 0 12 12") 
            .attr("refX","20")
            .attr("refY","6")
            .attr("orient","auto");

  var arrow_path = "M2,2 L10,6 L2,10 L6,6 L2,2";
  arrowMarker.append("path")
      .attr("d",arrow_path)
      .attr("fill","#000");

   var force = d3.layout.force()
        .nodes(nodes)
        .links(edges)
        .size([width,height])
        .linkDistance(200)
        .linkStrength(1)
        .gravity(0.1)
        .charge(-1000)
        .alpha(0.1)
        .start();

    var diagonal = d3.svg.diagonal()
        .projection(function(d) { return [d.x, d.y]; });
    // var svg_edges = svg.selectAll("line")
    //           .data(edges)
    //           .enter()
    //           .append("line")
    //           .attr("marker-end","url(#arrow)")
    //           // .style("stroke","#f00")
    //           .style("stroke-width",1);

      var svg_edges = svg.selectAll(".link")
              .data(edges)
              .enter()
              .append("path")
              .attr("class", "link inactive")
              .attr("marker-end","url(#arrow)")
              .attr("d", diagonal);
    var color = d3.scale.category20();      
    var svg_nodes = svg.selectAll("circle")
              .data(nodes)
              .enter()
              .append("circle")
              .attr("r",10)
              .attr("class","node inactive")
              .style("fill",function(d,i){
                return color(i);
              })
              .on("mouseover",function(d,i){  
                  d.show = true;
                  hilight();
              })  
              .on("mouseout",function(d,i){  
                  d.show = false; 
                  hilight(); 
              }).
              on("dblclick",function(d,i){
                addNodes(i);
              })
              .call(force.drag);
    var text_dx = -20;  
    var text_dy = 20;  
      
    var nodes_text = svg.selectAll(".nodetext")  
                    .data(nodes)  
                    .enter()  
                    .append("text")  
                    .attr("class","nodetext")  
                    .attr("dx",text_dx)  
                    .attr("dy",text_dy)  
                    .text(function(d){  
                        return d.name;  
                    });
    var addNodes = function(i){
        var ci = nodes.length;
        force.stop();
        nodes.push({name:'新人物'});
        edges.push( { source : i  , target: ci });
        force.start();
        svg_nodes
              .data(nodes)
              .enter()
              .append("circle")
              .attr("r",10)
              .attr("class","node inactive")
              .style("fill",function(d,i){
                return color(i);
              }).on("mouseover",function(d,i){  
                  d.show = true;
                  hilight();
              })  
              .on("mouseout",function(d,i){  
                  d.show = false; 
                  hilight(); 
              }).
              on("dblclick",function(d,i){
                addNodes(i);
              })
              .call(force.drag);
        svg_nodes = svg.selectAll("circle");
        svg_edges
              .data(edges)
              .enter()
              .append("path")
              .attr("class", "link inactive")
              .attr("marker-end","url(#arrow)")
              .attr("d", diagonal);
        svg_edges = svg.selectAll(".link");
    };
    var hilight = function(){
       var showNodes = [];
       svg_edges.each(function(d,i){
          d3.select(this).classed('inactive',!d.source.show&&!d.target.show);
          if(d.source.show)showNodes.push(d.target);
          if(d.target.show)showNodes.push(d.source);
       });
       svg_nodes.classed('inactive',function(d){
          return !d.show;
       });

       svg_nodes.filter(function(d,i){
        for(var idx=0;idx < showNodes.length; idx++){
          if(showNodes[idx].index == i)return true;
        }
        return false;
       }).classed('inactive',false);
    };

    force.on("tick", function(){
        nodes.forEach(function(d,i){  
            d.x = d.x - img_w/2 < 0     ? img_w/2 : d.x ;  
            d.x = d.x + img_w/2 > width ? width - img_w/2 : d.x ;  
            d.y = d.y - img_h/2 < 0      ? img_h/2 : d.y ;  
            d.y = d.y + img_h/2  > height ? height - img_h/2  : d.y ;  
        }); 
        svg_edges.attr("d", diagonal);
    
       // svg_edges.attr("x1",function(d){ return d.source.x; });
       // svg_edges.attr("y1",function(d){ return d.source.y; });
       // svg_edges.attr("x2",function(d){ return d.target.x; });
       // svg_edges.attr("y2",function(d){ return d.target.y; });
       svg_nodes.attr("cx",function(d){ return d.x; });
       svg_nodes.attr("cy",function(d){ return d.y; });
       nodes_text.attr("x",function(d){ return d.x });  
        nodes_text.attr("y",function(d){ return d.y + img_w/2; });  
        
    });
    </script> 
</html>  
